using System;
using System.Text;
using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Serial;

namespace HslCommunication.Profinet.Omron
{
	/// <summary>
	/// 欧姆龙的HostLink的C-Mode实现形式
	/// </summary>
	public class OmronHostLinkCMode : SerialDeviceBase
	{
		/// <inheritdoc cref="P:HslCommunication.Profinet.Omron.OmronHostLinkOverTcp.UnitNumber" />
		public byte UnitNumber
		{
			get;
			set;
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Omron.OmronFinsNet.#ctor" />
		public OmronHostLinkCMode()
		{
			base.ByteTransform = new ReverseWordTransform();
			base.WordLength = 1;
			base.ByteTransform.DataFormat = DataFormat.CDAB;
			base.ByteTransform.IsStringReverseByteWord = true;
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Omron.OmronFinsNet.Read(System.String,System.UInt16)" />
		public override OperateResult<byte[]> Read(string address, ushort length)
		{
			OperateResult<byte[]> operateResult = BuildReadCommand(address, length, isBit: false);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(PackCommand(operateResult.Content));
			if (!operateResult2.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult2);
			}
			OperateResult<byte[]> operateResult3 = ResponseValidAnalysis(operateResult2.Content, isRead: true);
			if (!operateResult3.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult3);
			}
			return OperateResult.CreateSuccessResult(operateResult3.Content);
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Omron.OmronFinsNet.Write(System.String,System.Byte[])" />
		public override OperateResult Write(string address, byte[] value)
		{
			OperateResult<byte[]> operateResult = BuildWriteWordCommand(address, value);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(PackCommand(operateResult.Content));
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			OperateResult<byte[]> operateResult3 = ResponseValidAnalysis(operateResult2.Content, isRead: false);
			if (!operateResult3.IsSuccess)
			{
				return operateResult3;
			}
			return OperateResult.CreateSuccessResult();
		}

		/// <summary>
		/// 读取PLC的当前的型号信息
		/// </summary>
		/// <returns>型号</returns>
		public OperateResult<string> ReadPlcModel()
		{
			OperateResult<byte[]> operateResult = ReadBase(PackCommand(Encoding.ASCII.GetBytes("MM")));
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<string>(operateResult);
			}
			int num = Convert.ToInt32(Encoding.ASCII.GetString(operateResult.Content, 5, 2), 16);
			if (num > 0)
			{
				return new OperateResult<string>(num, "Unknown Error");
			}
			string @string = Encoding.ASCII.GetString(operateResult.Content, 7, 2);
			return @string switch
			{
				"30" => OperateResult.CreateSuccessResult("CS/CJ"), 
				"01" => OperateResult.CreateSuccessResult("C250"), 
				"02" => OperateResult.CreateSuccessResult("C500"), 
				"03" => OperateResult.CreateSuccessResult("C120/C50"), 
				"09" => OperateResult.CreateSuccessResult("C250F"), 
				"0A" => OperateResult.CreateSuccessResult("C500F"), 
				"0B" => OperateResult.CreateSuccessResult("C120F"), 
				"0E" => OperateResult.CreateSuccessResult("C2000"), 
				"10" => OperateResult.CreateSuccessResult("C1000H"), 
				"11" => OperateResult.CreateSuccessResult("C2000H/CQM1/CPM1"), 
				"12" => OperateResult.CreateSuccessResult("C20H/C28H/C40H, C200H, C200HS, C200HX/HG/HE (-ZE)"), 
				"20" => OperateResult.CreateSuccessResult("CV500"), 
				"21" => OperateResult.CreateSuccessResult("CV1000"), 
				"22" => OperateResult.CreateSuccessResult("CV2000"), 
				"40" => OperateResult.CreateSuccessResult("CVM1-CPU01-E"), 
				"41" => OperateResult.CreateSuccessResult("CVM1-CPU11-E"), 
				"42" => OperateResult.CreateSuccessResult("CVM1-CPU21-E"), 
				_ => new OperateResult<string>("Unknown model, model code:" + @string), 
			};
		}

		/// <inheritdoc />
		public override string ToString()
		{
			return $"OmronHostLinkCMode[{base.PortName}:{base.BaudRate}]";
		}

		/// <summary>
		/// 将普通的指令打包成完整的指令
		/// </summary>
		/// <param name="cmd">fins指令</param>
		/// <returns>完整的质量</returns>
		private byte[] PackCommand(byte[] cmd)
		{
			byte[] array = new byte[7 + cmd.Length];
			array[0] = 64;
			array[1] = SoftBasic.BuildAsciiBytesFrom(UnitNumber)[0];
			array[2] = SoftBasic.BuildAsciiBytesFrom(UnitNumber)[1];
			array[array.Length - 2] = 42;
			array[array.Length - 1] = 13;
			cmd.CopyTo(array, 3);
			int num = array[0];
			for (int i = 1; i < array.Length - 4; i++)
			{
				num ^= array[i];
			}
			array[array.Length - 4] = SoftBasic.BuildAsciiBytesFrom((byte)num)[0];
			array[array.Length - 3] = SoftBasic.BuildAsciiBytesFrom((byte)num)[1];
			string @string = Encoding.ASCII.GetString(array);
			Console.WriteLine(@string);
			return array;
		}

		/// <summary>
		/// 解析欧姆龙的数据地址，参考来源是Omron手册第188页，比如D100， E1.100<br />
		/// Analyze Omron's data address, the reference source is page 188 of the Omron manual, such as D100, E1.100
		/// </summary>
		/// <param name="address">数据地址</param>
		/// <param name="isBit">是否是位地址</param>
		/// <param name="isRead">是否读取</param>
		/// <returns>解析后的结果地址对象</returns>
		public static OperateResult<string, string> AnalysisAddress(string address, bool isBit, bool isRead)
		{
			OperateResult<string, string> operateResult = new OperateResult<string, string>();
			try
			{
				switch (address[0])
				{
				case 'D':
				case 'd':
					operateResult.Content1 = (isRead ? "RD" : "WD");
					break;
				case 'C':
				case 'c':
					operateResult.Content1 = (isRead ? "RR" : "WR");
					break;
				case 'H':
				case 'h':
					operateResult.Content1 = (isRead ? "RH" : "WH");
					break;
				case 'A':
				case 'a':
					operateResult.Content1 = (isRead ? "RJ" : "WJ");
					break;
				case 'E':
				case 'e':
				{
					string[] array = address.Split(new char[1]
					{
						'.'
					}, StringSplitOptions.RemoveEmptyEntries);
					int num = Convert.ToInt32(array[0].Substring(1), 16);
					operateResult.Content1 = (isRead ? "RE" : "WE") + Encoding.ASCII.GetString(SoftBasic.BuildAsciiBytesFrom((byte)num));
					break;
				}
				default:
					throw new Exception(StringResources.Language.NotSupportedDataType);
				}
				if (address[0] == 'E' || address[0] == 'e')
				{
					string[] array2 = address.Split(new char[1]
					{
						'.'
					}, StringSplitOptions.RemoveEmptyEntries);
					if (!isBit)
					{
						operateResult.Content2 = ushort.Parse(array2[1]).ToString("D4");
					}
				}
				else if (!isBit)
				{
					operateResult.Content2 = ushort.Parse(address.Substring(1)).ToString("D4");
				}
			}
			catch (Exception ex)
			{
				operateResult.Message = ex.Message;
				return operateResult;
			}
			operateResult.IsSuccess = true;
			return operateResult;
		}

		/// <summary>
		/// 根据读取的地址，长度，是否位读取创建Fins协议的核心报文<br />
		/// According to the read address, length, whether to read the core message that creates the Fins protocol
		/// </summary>
		/// <param name="address">地址，具体格式请参照示例说明</param>
		/// <param name="length">读取的数据长度</param>
		/// <param name="isBit">是否使用位读取</param>
		/// <returns>带有成功标识的Fins核心报文</returns>
		public static OperateResult<byte[]> BuildReadCommand(string address, ushort length, bool isBit)
		{
			OperateResult<string, string> operateResult = AnalysisAddress(address, isBit, isRead: true);
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(operateResult.Content1);
			stringBuilder.Append(operateResult.Content2);
			stringBuilder.Append(length.ToString("D4"));
			return OperateResult.CreateSuccessResult(Encoding.ASCII.GetBytes(stringBuilder.ToString()));
		}

		/// <summary>
		/// 根据读取的地址，长度，是否位读取创建Fins协议的核心报文<br />
		/// According to the read address, length, whether to read the core message that creates the Fins protocol
		/// </summary>
		/// <param name="address">地址，具体格式请参照示例说明</param>
		/// <param name="value">等待写入的数据</param>
		/// <returns>带有成功标识的Fins核心报文</returns>
		public static OperateResult<byte[]> BuildWriteWordCommand(string address, byte[] value)
		{
			OperateResult<string, string> operateResult = AnalysisAddress(address, isBit: false, isRead: false);
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(operateResult.Content1);
			stringBuilder.Append(operateResult.Content2);
			for (int i = 0; i < value.Length / 2; i++)
			{
				stringBuilder.Append(BitConverter.ToUInt16(value, i * 2).ToString("X4"));
			}
			return OperateResult.CreateSuccessResult(Encoding.ASCII.GetBytes(stringBuilder.ToString()));
		}

		/// <summary>
		/// 验证欧姆龙的Fins-TCP返回的数据是否正确的数据，如果正确的话，并返回所有的数据内容
		/// </summary>
		/// <param name="response">来自欧姆龙返回的数据内容</param>
		/// <param name="isRead">是否读取</param>
		/// <returns>带有是否成功的结果对象</returns>
		public static OperateResult<byte[]> ResponseValidAnalysis(byte[] response, bool isRead)
		{
			if (response.Length >= 11)
			{
				int num = Convert.ToInt32(Encoding.ASCII.GetString(response, 5, 2), 16);
				byte[] array = null;
				if (response.Length > 11)
				{
					byte[] array2 = new byte[(response.Length - 11) / 2];
					for (int i = 0; i < array2.Length / 2; i++)
					{
						BitConverter.GetBytes(Convert.ToUInt16(Encoding.ASCII.GetString(response, 7 + 4 * i, 4), 16)).CopyTo(array2, i * 2);
					}
					array = array2;
				}
				if (num > 0)
				{
					return new OperateResult<byte[]>
					{
						ErrorCode = num,
						Content = array
					};
				}
				return OperateResult.CreateSuccessResult(array);
			}
			return new OperateResult<byte[]>(StringResources.Language.OmronReceiveDataError);
		}
	}
}
